Add a LRU cache to limit indexing memory usage. - #2079
Conversation
|
cc @art-w if you want to have a quick 🍔 look ? |
| } | ||
| let resolve_filename store ~filename = | ||
| if Filename.is_relative filename then | ||
| Filename.concat (Filename.dirname store.filename) filename |
There was a problem hiding this comment.
nitpick: I believe filename could contain ../../ (introduced in relativize below), which could mess up relativize when we write later? (I guess the result wouldn't be wrong but would have ../../path/../otherpath)
| could lead to memory leaks if the user of the cache keeps a reference | ||
| to the cell. *) |
There was a problem hiding this comment.
There are some TODOs here with nice ideas :) (but not essentials)
|
Thanks a lot for the review @art-w. I think I addressed all the important comments. These are probably worth a re-review 🙂 |
|
I ran two benchmarks with a LRU large enough to store the entire date. One that builds Merlin's
One that aggregates all of Merlin indexes:
So we loose a bit of the improvements that pointing indexes brought, but we are still much faster at aggregating than before this work. The most likely explanation for the slowdown is the move to a functional union-find, which is a necessary evil. I think these results are quite good overall, with an aggregation that is twice as fast as before. |
|
And index sizes:
These are the index built by And the size of the aggregate of all these indexes:
|
art-w
left a comment
There was a problem hiding this comment.
Thanks! It's looking good, I only have some minor questions/suggestions
| index.related_uids | ||
| index.related_uids; | ||
| Uid_map.schema type_ufstore iter | ||
| (fun _iter _uid _content -> ()) |
There was a problem hiding this comment.
Don't we need to schema iter on the Uid_set.t stored in _content?
There was a problem hiding this comment.
Currently the Uid_set is not granular: module Uid_set = Shape.Uid.Set.
Should we make it granular ? I did that in d8aa258
It required removing some fast-paths in Union_find.union that were relying on polymorphic comparison. If it turns out to be important we can add an equal function to granular set.
| Uid_map.fold | ||
| (fun uid content store -> | ||
| match content with | ||
| | Root _ -> ensure store uid |
There was a problem hiding this comment.
If ensure terminates early because Uid_map.mem uid s1 and there are no Link to that Root in s2, then I believe we need to compute the Uid_set.union of s2 with s1? (otherwise store will only have the s1 set?)
(or is it the case that if we only have a root-with-no-link then the uid set is the singleton {uid} which is guaranteed to be in the s1 set anyway?)
There was a problem hiding this comment.
I think we don't even have "roots with no link" since we always register at least a pair of uids during the indexing...
|
My changes following the latest review do not have any significant performance impact. |
|
Ok, I think I addressed all your remaining comments @art-w ! |
- Change the way small values are handled by storing them along their parent. - Make filenames relative to the current working directory of the indexer. - Disable related-uids compression Suggested-by: ArthurW <arthur@tarides.com> Co-authored-by: Lucccyo <cha.git@mailo.fr> Co-authored-by: Tim ats <tim.arnouts@protonmail.com> Co-authored-by: ArthurW <arthur@tarides.com>
Before we could rely on deduplicate to flag links worth caching, but now we have both the LRU which could trigger multiple reads to the same loc and the smalls pointing to parents (which are potentially not marked as Serialized_reused) Suggested-by: ArthurW <arthur@tarides.com>
This required removing a fast-path in Union_find.union that was relying on polymorphic comparison. I it turns out to be important we can add an equal function to granular set.
|
Thank you for the thorough review @art-w. Merging now. |
This work is based on #2050